package com.framework.service.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.framework.common.Enums.FrameworkErrorCodeEnum;
import com.framework.common.constant.Constants;
import com.framework.common.domain.R;
import com.framework.common.util.Base64Util;
import com.framework.common.util.HttpUtil;
import com.framework.common.util.RedisUtils;
import com.framework.service.core.service.ICommonSdkService;
import com.framework.service.core.service.IFileService;
import com.framework.core.api.response.IdentityRes;
import com.framework.core.api.response.UploadRes;
import com.framework.service.core.service.ICommonSdkService;
import com.framework.service.core.service.IFileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Set;

/**
 * 外部sdk接口通用方法
 * @author zhoubb
 * @version V1.0
 * @Date 2020/4/26 21:48
 * @since JDK 1.8
 */
@Slf4j
@Service
public class CommonSdkServiceImpl implements ICommonSdkService {

    @Value("${aliyun.identityCardNoUrl}")
    private String identityCardNoUrl;

    @Value("${aliyun.identity.appcode}")
    private String aliyunIdentityAppCode;

    @Value("${aliyun.sms.code.url}")
    private String smsCodeUrl;

    @Value("${aliyun.sms.code.appcode}")
    private String smsCodeAppCode;

    @Value("${aliyun.sms.common.url}")
    private String smsCommonUrl;

    @Value("${aliyun.sms.common.appcode}")
    private String smsCommonAppCode;

    @Value("${baidu.sdk.appid}")
    private String baiduSdkAppid;

    @Value("${baidu.sdk.appkey}")
    private String baiduSdkAppkey;

    @Value("${baidu.sdk.secretkey}")
    private String baiduSdkSecretkey;

    @Value("${baidu.sdk.identityCardUrl}")
    private String baiduSdkIdentityCardUrl;

    @Value("${baidu.sdk.identityLicenseUrl}")
    private String baiduSdkIdentityLicenseUrl;

    @Value("${baidu.sdk.authUrl}")
    private String baiduSdkAuthUrl;


    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private IFileService fileService;

    @Override
    public String identityCardByAliyun(String cardNo) {
        if(StringUtils.isBlank(cardNo)) {
            log.warn("调用阿里云接口校验身份证，参数为空!cardNo=[{}]", cardNo);
            return null;
        }
        log.info("开始调用阿里云接口校验身份证,cardNo=[{}]", cardNo);
        // 组装api地址
        StringBuffer serverUrl = new StringBuffer(
                identityCardNoUrl.replace("#CARDNO",cardNo));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.set("Authorization", "APPCODE " + aliyunIdentityAppCode);
        HttpEntity<String> request = new HttpEntity<String>(headers);
        log.info("开始调用阿里云api校验身份证,url=[{}]", serverUrl);
        ResponseEntity<String> responseEntity = null;
        try {
            responseEntity = restTemplate.exchange(serverUrl.toString(), HttpMethod.GET, request, String.class);
        } catch (Exception e) {
            log.error("调用阿里云api校验身份证异常!", e);
            return null;
        }
        log.info("请求阿里云api校验身份证完成,响应结果=[{}]", JSON.toJSONString(responseEntity));
        if (!HttpStatus.OK.equals(responseEntity.getStatusCode()) || responseEntity.getBody() == null) {
            log.warn("调用阿里云api校验身份证失败, statusCode=[{}]", responseEntity.getStatusCode());
            return null;
        }
        return responseEntity.getBody();
    }

    @Override
    public String sendMessageForCodeByAliyun(String phone, String code) {
        if(StringUtils.isBlank(phone) || StringUtils.isBlank(code)) {
            log.warn("调用阿里云短信接口发送验证码，参数为空!phone=[{}]-code=[{}]", phone, code);
            return null;
        }
        log.info("开始调用阿里云短信接口发送验证码,phone=[{}]-code=[{}]", phone, code);
        // 组装api地址
        StringBuffer smsUrl = new StringBuffer(
                smsCodeUrl.replace("#PHONE",phone).replace("#CODE",code));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.set("Authorization", "APPCODE " + smsCodeAppCode);
        HttpEntity<String> request = new HttpEntity<String>(headers);
        log.info("调用阿里云短信接口发送验证码,url=[{}]", smsUrl);
        ResponseEntity<String> responseEntity = null;
        try {
            responseEntity = restTemplate.exchange(smsUrl.toString(), HttpMethod.GET, request, String.class);
        } catch (Exception e) {
            log.error("调用阿里云短信接口发送验证码异常!", e);
            return null;
        }
        log.info("请求调用阿里云短信接口发送验证码完成,响应结果=[{}]", JSON.toJSONString(responseEntity));
        if (!HttpStatus.OK.equals(responseEntity.getStatusCode()) || responseEntity.getBody() == null) {
            log.warn("调用阿里云短信接口发送验证码, statusCode=[{}]", responseEntity.getStatusCode());
            return null;
        }
        return responseEntity.getBody();
    }

    @Override
    public String sendMessageByAliyun(String phone, String params, String skin) {
        if(StringUtils.isBlank(phone) || StringUtils.isBlank(params) || StringUtils.isBlank(skin)) {
            log.warn("调用阿里云短信接口发送订单信息，参数为空!phone=[{}]-params=[{}]-skin=[{}]", phone, params, skin);
            return null;
        }
        log.info("开始调用阿里云短信接口发送订单信息,phone=[{}]-params=[{}]-skin=[{}]", phone, params, skin);
        // 组装api地址
        StringBuffer smsUrl = new StringBuffer(
                smsCommonUrl.replace("#PHONE",phone).replace("#PARAM",params)
        .replace("#SKIN", skin));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.set("Authorization", "APPCODE " + smsCommonAppCode);
        HttpEntity<String> request = new HttpEntity<String>(headers);
        log.info("调用阿里云短信接口发送订单信息,url=[{}]", smsUrl);
        ResponseEntity<String> responseEntity = null;
        try {
            responseEntity = restTemplate.exchange(smsUrl.toString(), HttpMethod.GET, request, String.class);
        } catch (Exception e) {
            log.error("调用阿里云短信接口发送订单信息异常!", e);
            return null;
        }
        log.info("请求调用阿里云短信接口发送订单信息完成,响应结果=[{}]", JSON.toJSONString(responseEntity));
        if (!HttpStatus.OK.equals(responseEntity.getStatusCode()) || responseEntity.getBody() == null) {
            log.warn("调用阿里云短信接口发送订单信息, statusCode=[{}]", responseEntity.getStatusCode());
            return null;
        }
        return responseEntity.getBody();
    }

    @Override
    public String sendMessageForProcess(String openId, String type, String title) {
        if(StringUtils.isBlank(openId) || StringUtils.isBlank(type) || StringUtils.isBlank(title)) {
            log.warn("调用阿里云短信接口发送订单提醒信息，参数为空!openId=[{}]-type=[{}]-title=[{}]", openId, type, title);
            return null;
        }
        log.info("开始调用阿里云短信接口发送订单提醒信息,openId=[{}]-type=[{}]-title=[{}]", openId, type, title);

//        // 组装api地址
//        StringBuffer smsUrl = new StringBuffer(
//                smsCommonUrl.replace("#PHONE",phone).replace("#PARAM",params)
//                        .replace("#SKIN", skin));
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//        headers.set("Authorization", "APPCODE " + smsCommonAppCode);
//        HttpEntity<String> request = new HttpEntity<String>(headers);
//        log.info("调用阿里云短信接口发送订单信息,url=[{}]", smsUrl);
//        ResponseEntity<String> responseEntity = null;
//        try {
//            responseEntity = restTemplate.exchange(smsUrl.toString(), HttpMethod.GET, request, String.class);
//        } catch (Exception e) {
//            log.error("调用阿里云短信接口发送订单信息异常!", e);
//            return null;
//        }
//        log.info("请求调用阿里云短信接口发送订单信息完成,响应结果=[{}]", JSON.toJSONString(responseEntity));
//        if (!HttpStatus.OK.equals(responseEntity.getStatusCode()) || responseEntity.getBody() == null) {
//            log.warn("调用阿里云短信接口发送订单信息, statusCode=[{}]", responseEntity.getStatusCode());
//            return null;
//        }
//        return responseEntity.getBody();
        return null;
    }

    @Override
    public R identityCardByBaidu(String cardImg, String imgSide) {
        if(StringUtils.isBlank(cardImg) || StringUtils.isBlank(imgSide)) {
            log.warn("调用百度sdk识别身份证照片，参数为空!cardImg=[{}]-imgSide=[{}]", cardImg, imgSide);
            return null;
        }
        log.info("开始调用百度sdk识别身份证照片,imgSide=[{}]",imgSide);
        // 判断redis中是否已存在access_token
        String accessToken = null;
        if(!redisUtils.hasKey(Constants.BAIDU_SDK_ACCESS_TOEKN_KEY)) {
            // 获取access_token
            accessToken = getBaiduAccessToken();
            redisUtils.set(Constants.BAIDU_SDK_ACCESS_TOEKN_KEY, accessToken);
        }
        accessToken = redisUtils.get(Constants.BAIDU_SDK_ACCESS_TOEKN_KEY);
        log.info("调用百度sdk识别身份证照片,accessToken获取成功");

        // 组装身份证识别sdk地址
        StringBuffer serverUrl = new StringBuffer(
                baiduSdkIdentityCardUrl.replace("#ACCESS_TOKEN",accessToken));

        try {
            if(cardImg.split(",").length > 1) {
                cardImg = cardImg.split(",")[1];
            }
            cardImg = cardImg.replaceAll("\r\n","");
            cardImg = cardImg.replaceAll("\\+","%2B");
            String param = "id_card_side=" + imgSide + "&image=" + cardImg;
            String result = HttpUtil.post(baiduSdkIdentityCardUrl, accessToken, param);
            JSONObject jsonObject = JSON.parseObject(result);
            log.info("调用百度sdk识别身份证照片,识别成功,结果=[{}]", result);
            if(StringUtils.equals("normal", jsonObject.getString("image_status"))) {
                return R.okData(jsonObject);
            }
            return R.error(FrameworkErrorCodeEnum.PICTURE_OCR_FAIL);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
    }

    @Override
    public R identityBusinessByBaidu(String licenseImg) {
        if(StringUtils.isBlank(licenseImg)) {
            log.warn("调用百度sdk识别营业执照照片，参数为空!cardImg=[{}]", licenseImg);
            return null;
        }
        log.info("调用百度sdk识别营业执照照片,开始");
        // 判断redis中是否已存在access_token
        String accessToken = null;
        if(!redisUtils.hasKey(Constants.BAIDU_SDK_ACCESS_TOEKN_KEY)) {
            // 获取access_token
            accessToken = getBaiduAccessToken();
            redisUtils.set(Constants.BAIDU_SDK_ACCESS_TOEKN_KEY, accessToken);
        }
        accessToken = redisUtils.get(Constants.BAIDU_SDK_ACCESS_TOEKN_KEY);
        log.info("调用百度sdk识别营业执照照片,accessToken获取成功");

        try {
            if(licenseImg.split(",").length > 1) {
                licenseImg = licenseImg.split(",")[1];
            }
            licenseImg = licenseImg.replaceAll("\r\n","");
            licenseImg = licenseImg.replaceAll("\\+","%2B");
            String param = "image=" + licenseImg;
            String result = HttpUtil.post(baiduSdkIdentityLicenseUrl, accessToken, param);
            JSONObject jsonObject = JSON.parseObject(result);
            log.info("调用百度sdk识别营业执照照片,识别成功,结果=[{}]", result);
            // 判断识别是否通过
            JSONObject resSub = (JSONObject) jsonObject.get("words_result");

            if (resSub.keySet().size() > 0) {
                Set<String> set=  resSub.keySet();
                Iterator<String> it = set.iterator();
                while(it.hasNext()){
                    String key = it.next();
                    if(!StringUtils.equals("无",JSON.parseObject(resSub.getString(key)).getString("words"))) {
                        return R.okData(jsonObject);
                    }
                }

            }
            return R.error(FrameworkErrorCodeEnum.PICTURE_OCR_FAIL);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
    }

    @Override
    public IdentityRes identityCardByBaidu(MultipartFile file, String imgSide) {
        log.info("[识别身份证照片并上传]-开始");
        IdentityRes identityRes = new IdentityRes();
        if(file == null) {
            log.warn("[识别身份证照片并上传]-文件不存在");
            identityRes.setCode(FrameworkErrorCodeEnum.FILE_NOT_EXISTS.getCode());
            identityRes.setMsg(FrameworkErrorCodeEnum.FILE_NOT_EXISTS.getMsg());
            return identityRes;
        }
        // 文件内容先转base64
        String imgParam = null;
        try {
            byte[] imgData = file.getBytes();
            String imgStr = Base64Util.encode(imgData);
            imgParam = URLEncoder.encode(imgStr, "UTF-8");
        } catch (IOException e) {
            log.error("[识别身份证照片并上传]-文件读取异常", e);
            identityRes.setCode(FrameworkErrorCodeEnum.FILE_READ_ERROR.getCode());
            identityRes.setMsg(FrameworkErrorCodeEnum.FILE_READ_ERROR.getMsg());
            return identityRes;
        }
        // 识别身份证
        R r = identityCardByBaidu(imgParam, imgSide);
        if((boolean)(r.get("success"))) {
            // 上传图片
            //UploadRes uploadRes = fileService.uploadFile(file);
            UploadRes uploadRes = fileService.uploadFileToOss(file);
            identityRes.setIdentityBody(r.get("data"));
            //identityRes.setIdentityBody(r.get(""));
            if(uploadRes.isSuccess()) {
                identityRes.setFilePath(uploadRes.getFilePath());
                identityRes.setCode(FrameworkErrorCodeEnum.SUCCESS.getCode());
                identityRes.setMsg(FrameworkErrorCodeEnum.SUCCESS.getMsg());
                log.info("[识别身份证照片并上传]-结束-结果=[{}]", JSON.toJSONString(identityRes));
                return identityRes;
            }
            identityRes.setCode(FrameworkErrorCodeEnum.FILE_UPLOAD_FAIL.getCode());
            identityRes.setMsg(FrameworkErrorCodeEnum.FILE_UPLOAD_FAIL.getMsg());
            log.info("[识别身份证照片并上传]-结束-结果=[{}]", JSON.toJSONString(identityRes));
            return identityRes;
        }
        identityRes.setCode(FrameworkErrorCodeEnum.IDCARD_OCR_FAIL.getCode());
        identityRes.setMsg(FrameworkErrorCodeEnum.IDCARD_OCR_FAIL.getMsg());
        log.info("[识别身份证照片并上传]-结束-结果=[{}]", JSON.toJSONString(identityRes));
        return identityRes;
    }

    @Override
    public IdentityRes identityBusinessByBaidu(MultipartFile file) {
        log.info("[识别营业执照并上传]-开始");
        IdentityRes identityRes = new IdentityRes();
        if(file == null) {
            log.warn("[识别营业执照并上传]-文件不存在");
            identityRes.setCode(FrameworkErrorCodeEnum.FILE_NOT_EXISTS.getCode());
            identityRes.setMsg(FrameworkErrorCodeEnum.FILE_NOT_EXISTS.getMsg());
            return identityRes;
        }
        // 文件内容先转base64
        String imgParam = null;
        try {
            byte[] imgData = file.getBytes();
            String imgStr = Base64Util.encode(imgData);
            imgParam = URLEncoder.encode(imgStr, "UTF-8");
        } catch (IOException e) {
            log.error("[识别营业执照并上传]-文件读取异常", e);
            identityRes.setCode(FrameworkErrorCodeEnum.FILE_READ_ERROR.getCode());
            identityRes.setMsg(FrameworkErrorCodeEnum.FILE_READ_ERROR.getMsg());
            return identityRes;
        }
        // 识别营业执照
        R r = identityBusinessByBaidu(imgParam);
        if((boolean)(r.get("success"))) {
            // 上传图片
            //UploadRes uploadRes = fileService.uploadFile(file);
            UploadRes uploadRes = fileService.uploadFileToOss(file);
            identityRes.setIdentityBody(r.get("data"));
            if(uploadRes.isSuccess()) {
                identityRes.setFilePath(uploadRes.getFilePath());
                identityRes.setCode(FrameworkErrorCodeEnum.SUCCESS.getCode());
                identityRes.setMsg(FrameworkErrorCodeEnum.SUCCESS.getMsg());
                log.info("[识别营业执照并上传]-结束-结果=[{}]", JSON.toJSONString(identityRes));
                return identityRes;
            }
            identityRes.setCode(FrameworkErrorCodeEnum.FILE_UPLOAD_FAIL.getCode());
            identityRes.setMsg(FrameworkErrorCodeEnum.FILE_UPLOAD_FAIL.getMsg());
            log.info("[识别营业执照并上传]-结束-结果=[{}]", JSON.toJSONString(identityRes));
            return identityRes;
        }

        identityRes.setCode(FrameworkErrorCodeEnum.BUSINESS_OCR_FAIL.getCode());
        identityRes.setMsg(FrameworkErrorCodeEnum.BUSINESS_OCR_FAIL.getMsg());
        log.info("[识别营业执照并上传]-结束-结果=[{}]", JSON.toJSONString(identityRes));
        return identityRes;
    }

    /**
     * 获取百度accessToken
     * @return
     */
    private String getBaiduAccessToken() {
        StringBuffer serverUrl = new StringBuffer(
                baiduSdkAuthUrl.replace("#APIKEY",baiduSdkAppkey)
                        .replace("#SECRETKEY", baiduSdkSecretkey));
        ResponseEntity<String> responseEntity = null;
        try{
            responseEntity = callBaiduApi(serverUrl.toString());
        } catch (Exception e) {
            log.error("调用百度sdk接口accessToken异常!", e);
            return null;
        }
        log.info("请求百度sdk接口获取access_token完成,响应结果=[{}]", JSON.toJSONString(responseEntity));
        if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
            log.warn("调用百度sdk接口获取access_token失败, statusCode=[{}]", responseEntity.getStatusCode());
            return null;
        }
        String accessToken = JSONObject.parseObject(responseEntity.getBody()).getString("access_token");
        return accessToken;
    }

    /**
     * 调用百度api
     * @param apiUrl
     * @return
     */
    private ResponseEntity<String> callBaiduApi(String apiUrl) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> request = new HttpEntity<String>(headers);
        log.info("开始请求百度api,url=[{}]", apiUrl);
        return restTemplate.exchange(apiUrl, HttpMethod.GET, request, String.class);
    }
}
